import { defineComponent, ref, watch, reactive, computed } from 'vue';
import getTool from '../tools/index';
import MyInput from './input';
import Textarea from './textarea';
import event from '../tools/event';
import fnModules from '../tools/fns';
import Toast from './toast';
const tools = getTool();
export default defineComponent({
  name: 'rowEditableTable',
  props: {
    tableData: {
      type: Array,
      default: () => [],
    },
    tableHeader: {
      type: Array,
      default: () => [],
    },
    bodyNotShowProps: {
      type: Array,
      default: () => [],
    },
    tableBorderColor: {
      type: String,
      default: '#ddd',
    },
    cellHeight: {
      type: Number,
      default: 40,
    },
    uniqueKey: {
      type: String,
      default: '',
    },
    firstThClickHandler: {
      type: Function,
      default: () => null,
    },
    isFirstThEableClick: {
      type: Boolean,
      default: false,
    },
    firstThStyle: {
      type: Object,
      default: () => ({}),
    },
    isReadOnly: {
      type: Boolean,
      default: false,
    },
    bodyEmptyTips: {
      type: String,
      default: '暂无数据',
    },
    headerStyle: {
      type: Object,
      default: () => ({
        background: '#f5f7fa',
        color: '#333',
      }),
    },
    cellStyle: {
      type: Object,
      default: () => ({
        background: '#fff',
        color: '#333',
      }),
    },
    calcCellStyle: {
      type: Object,
      default: () => ({
        background: '#999',
        color: '#fff',
      }),
    },
  },
  setup(props) {
    const ossTableHeader = ref([]);
    const ossTableData = reactive([]);
    const onlyOneCellBodyArr = ref([]);
    const headerArr = ref([]);
    const bodyNotShowPropData = ref(['cell_id']);
    const curTableData = reactive([]);
    const curEditTdId = ref('');
    const textAreaContent = ref('');
    const isBodyEmpty = ref(false);
    const rowComponentName = 'rowEditableTable';
    const oneCellData = reactive({
      code: '',
      key: '',
    });

    const getRowspan = (cell) => {
      return cell.rowSpan ? cell.rowSpan : 1;
    };

    const renderHeader = (item, _idx) => {
      const common = {
        verticalAlign: 'middle',
        borderLeft: `1px solid ${props.tableBorderColor}`,
      };
      return (
        <th
          rowspan={getRowspan(item)}
          colspan={item.colSpan ? item.colSpan : 1}
          style={
            _idx === 0 && props.isFirstThEableClick && item.sortIdx === '0' && item.classifyId === 0
              ? {
                  ...common,
                  ...props.firstThStyle,
                  cursor: 'pointer',
                  height: `${props.cellHeight * getRowspan(item)}px`,
                }
              : {
                  ...common,
                  height: `${props.cellHeight * getRowspan(item)}px`,
                }
          }
          onClick={() => {
            if (
              !props.isFirstThEableClick ||
              _idx !== 0 ||
              item.sortIdx !== '0' ||
              item.classifyId !== 0
            ) {
              return;
            }
            props.firstThClickHandler();
          }}
        >
          <span>{item.title}</span>
        </th>
      );
    };

    const getOneCellItemByKey = (key, arr = onlyOneCellBodyArr.value) => {
      const temp = arr.find((item) => {
        if (item.key) {
          return item.key === key;
        } else if (item.children && item.children.length) {
          return getOneCellItemByKey(key, item.children);
        }
      });
      return temp;
    };

    const tdClickHandler = (tableId) => {
      curEditTdId.value = tableId;
    };

    const isAfrontB = (A, B) => {
      if (!A || !B) {
        return 0;
      }
      const A_arr = A.split('_').map((item) => Number(item));
      const B_arr = B.split('_').map((item) => Number(item));
      const len = Math.min(...[A_arr.length, B_arr.length]);
      for (let i = 0; i < len; i++) {
        if (A_arr[i] - B_arr[i] > 0) {
          return 1;
        } else if (A_arr[i] - B_arr[i] < 0) {
          return -1;
        }
      }
      return 0;
    };

    const getHeaderItemSortIndex = (target_key) => {
      const _idx = headerArr.value.findIndex((item) => item.key === target_key);
      if (_idx === -1) {
        return '';
      }
      return headerArr.value[_idx].sortIdx;
    };

    const renderTableColumn = (colOptions) => {
      const sortArr = Object.keys(colOptions)
        .filter(
          (item) =>
            !bodyNotShowPropData.value.includes(item) &&
            item !== 'undefined' &&
            !bodyNotShowPropData.value.includes(item) &&
            !getOneCellItemByKey(item),
        )
        .sort((a, b) => {
          try {
            return isAfrontB(getHeaderItemSortIndex(a), getHeaderItemSortIndex(b));
          } catch (e) {
            throw e;
          }
        });

      return (
        <tr style={{ width: '100%' }}>
          {sortArr.map((item, idx) => {
            const readonlyInput = (() => {
              const common = {
                ...props.cellStyle,
                minWidth: '100px',
                borderTop: 'none',
                borderBottom: 'none',
                borderLeft: `1px solid ${props.tableBorderColor}`,
                borderRight: 'none',
                borderRadius: 0,
                textAlign: 'center',
              };
              return (
                <MyInput
                  addStyle={
                    colOptions[item].fn
                      ? {
                          ...common,
                          ...props.calcCellStyle,
                        }
                      : {
                          ...common,
                        }
                  }
                  parentColumnId={
                    props.uniqueKey
                      ? colOptions[props.uniqueKey]
                        ? colOptions[props.uniqueKey]
                        : colOptions['table_id']
                      : colOptions['table_id']
                  }
                  componentName={rowComponentName}
                  editPropName={item}
                  isReadonly
                  value={
                    typeof colOptions[item] === 'object' ? colOptions[item].value : colOptions[item]
                  }
                />
              );
            })();
            const editInput = (() => {
              return (
                <MyInput
                  style={{ minWidth: '100px' }}
                  addStyle={
                    `td_id_${colOptions[props.uniqueKey]}_${item}_${idx}` !== curEditTdId.value
                      ? {
                          ...props.cellStyle,
                          borderTop: 'none',
                          borderBottom: 'none',
                          borderLeft: `1px solid ${props.tableBorderColor}`,
                          borderRight: 'none',
                          borderRadius: 0,
                          textAlign: 'center',
                        }
                      : {
                          textAlign: 'center',
                        }
                  }
                  parentColumnId={
                    props.uniqueKey
                      ? colOptions[props.uniqueKey]
                        ? colOptions[props.uniqueKey]
                        : colOptions['table_id']
                      : colOptions['table_id']
                  }
                  componentName={rowComponentName}
                  editPropName={item}
                  value={
                    typeof colOptions[item] === 'object' ? colOptions[item].value : colOptions[item]
                  }
                />
              );
            })();
            return bodyNotShowPropData.value.includes(item) ? null : (
              <td
                class="row-td "
                id={`td_id_${colOptions[props.uniqueKey]}_${item}_${idx}`}
                style={{
                  borderBottom: `1px solid ${props.tableBorderColor}`,
                  width: `${(1 / ossTableHeader.value.length) * 100}%`,
                  verticalAlign: 'middle',
                }}
                onClick={() =>
                  tdClickHandler(`td_id_${colOptions[props.uniqueKey]}_${item}_${idx}`)
                }
              >
                {props.isReadOnly
                  ? readonlyInput
                  : getHeaderItemByKey(item) && getHeaderItemByKey(item).isCanEdit
                  ? typeof colOptions[item] === 'object' && !colOptions[item].isCanEdit
                    ? readonlyInput
                    : editInput
                  : readonlyInput}
              </td>
            );
          })}
        </tr>
      );
    };

    const getValueFromColumn = (code, key) => {
      const _target = curTableData.value.find((item) => item[props.uniqueKey] === code);
      if (_target) {
        if (typeof _target[key] === 'object') {
          return _target[key].value ? _target[key].value : 0;
        } else {
          return _target[key] ? _target[key] : 0;
        }
      } else {
        return '';
      }
    };

    const checkIfNum = (n) => {
      return !Object.is(Number(n), NaN) ? Number(n) : 0;
    };

    const initData = () => {
      headerArr.value = [];
      onlyOneCellBodyArr.value = [];
      ossTableHeader.value = tools.deepCopy(props.tableHeader);
      ossTableData.value = tools.deepCopy(props.tableData);
      curTableData.value = tools.deepCopy(props.tableData);
      if (props.tableData.length && props.tableData[0][props.uniqueKey]) {
        oneCellData.code = props.tableData[0][props.uniqueKey];
      }
      isBodyEmpty.value = !ossTableData.value.length;
      bodyNotShowPropData.value = [
        ...new Set([...bodyNotShowPropData.value, ...props.bodyNotShowProps]),
      ];

      ossTableData.value.forEach((item) => {
        if (!props.uniqueKey) {
          if (!item.cell_id) {
            item.cell_id = tools.guid();
          }
        } else {
          if (!item.cell_id) {
            item.cell_id = item[props.uniqueKey];
          }
        }
      });

      ossTableHeader.value = giveIdx2Item(ossTableHeader.value);
      ossTableHeader.value.forEach((item, idx) => {
        if (item.onlyOneCell) {
          const _temp = item;
          const _idx = onlyOneCellBodyArr.value.findIndex((i) => i.key === _temp.key);
          if (_idx === -1) {
            onlyOneCellBodyArr.value.push(_temp);
            oneCellData.key = _temp.key;
            if (props.tableData.length) {
              textAreaContent.value = props.tableData[0][_temp.key];
            }
          }
        }
        setTimeout(() => {
          ossTableHeader.value.splice(idx, 1);
        }, 0);
      });

      getHeaderItemArr(ossTableHeader.value);
    };

    const giveIdx2Item = (arr, parentSortId = '', classifyId = 0) => {
      return arr.map((v, idx) => {
        const item = {
          ...tools.deepCopy(v),
          sortIdx: '',
          classifyId: -1,
        };

        if (!item.sortIdx) {
          item.sortIdx = (parentSortId ? parentSortId + '_' : '') + idx;
        }
        item.classifyId = classifyId;
        if (item.children && item.children.length) {
          item.children = giveIdx2Item(item.children, item.sortIdx, classifyId + 1);
        }
        return item;
      });
    };

    const getHeaderItemArr = (arr1) => {
      const bianli = (arr) => {
        arr.forEach((item, idx) => {
          if (item.onlyOneCell) {
            const _temp = item;
            const _idx = onlyOneCellBodyArr.value.findIndex((i) => i.key === _temp.key);
            if (_idx === -1) {
              onlyOneCellBodyArr.value.push(_temp);
              oneCellData.key = _temp.key;
              if (props.tableData.length) {
                textAreaContent.value = props.tableData[0][_temp.key];
              }
            }
            arr.splice(idx, 1);
            return;
          }
          if (item.children && item.children.length) {
            const idx = headerArr.value.findIndex(
              (val) => val.title === item.title && val.sortIdx === item.sortIdx,
            );
            if (idx === -1) {
              const _temp = tools.deepCopy(item);
              delete _temp.children;
              headerArr.value.push(_temp);
            }
            bianli(item.children);
          } else {
            const _idx = headerArr.value.findIndex((val) => val.key === item.key);
            if (_idx === -1) {
              headerArr.value.push(item);
            }
          }
        });
      };
      bianli(arr1);
    };

    const renderOneCellItem = () => {
      if (!onlyOneCellBodyArr.value.length) {
        return null;
      }
      return (
        <div class="flexBox flex-ver-box alItSt" style={{ width: '300px' }}>
          {renderOneCellHeader()}
          {onlyOneCellBodyArr.value.map((item) => {
            return (
              <div
                class="flexBox flex-ver-box alItSt "
                style={{
                  overflow: 'hidden',
                  border: `1px solid ${props.tableBorderColor}`,
                  borderLeft: 'none',
                  borderTop: 'none',
                  width: '300px',
                }}
                key={item.key}
              >
                {isBodyEmpty.value ? null : (
                  <Textarea
                    addStyle={{
                      ...props.cellStyle,
                      height: `${ossTableData.value.length * 40 + ossTableData.value.length - 1}px`,
                    }}
                    propContent={textAreaContent.value}
                    isReadonly={props.isReadOnly}
                  />
                )}
              </div>
            );
          })}
        </div>
      );
    };
    const getHeaderItemByKey = (key) => {
      const _temp = headerArr.value.find((item) => item.key === key);
      return _temp;
    };
    const renderOneCellHeader = () => {
      const getOneCellHeaderArr = (origArr, resArr = []) => {
        const arr = tools.deepCopy(origArr);
        arr.forEach((item) => {
          const _temp = tools.deepCopy(item);
          delete _temp.children;
          resArr.push(_temp);
          if (item.children && item.children.length) {
            getOneCellHeaderArr(item.children, resArr);
          }
        });
        return resArr;
      };
      const oneCellHeaderArr = getOneCellHeaderArr(onlyOneCellBodyArr.value).filter(
        (item) => item.title,
      );

      return (
        <div style={{ borderTop: `1px solid ${props.tableBorderColor}` }}>
          {oneCellHeaderArr.map((item) => {
            return (
              <div
                id={item.title}
                style={{
                  ...props.headerStyle,
                  lineHeight: `${props.cellHeight * item.rowSpan}px`,
                  borderRight: `1px solid ${props.tableBorderColor}`,
                  borderBottom: `1px solid ${props.tableBorderColor}`,
                  width: '300px',
                }}
                class="flexBox Ellipsis"
              >
                <span style={{ padding: '0 20px' }}>{item.title}</span>
              </div>
            );
          })}
        </div>
      );
    };

    const renderPanelBody = () => {
      const renderBody = () => {
        return (
          <tbody style={{ borderTop: `1px solid ${props.tableBorderColor}` }}>
            {ossTableData.value.map((item) => {
              return renderTableColumn(item);
            })}
          </tbody>
        );
      };

      return (
        <div>
          <table
            style={{
              width: '100%',
              border: `1px solid ${props.tableBorderColor}`,
              borderBottom: 'none',
              borderLeft: 'none',
            }}
          >
            <thead>
              {headerArr.value.map((val) => {
                return (
                  <tr
                    style={{
                      ...props.headerStyle,
                      borderTop: `1px solid ${props.tableBorderColor}`,
                    }}
                  >
                    {headerArr.value
                      .filter((item) => item.classifyId === val.classifyId)
                      .filter((item) => item.title)
                      .map((item, _idx) => {
                        return renderHeader(item, _idx);
                      })}
                  </tr>
                );
              })}
            </thead>
            {renderBody()}
          </table>
        </div>
      );
    };

    const emptyBody = () => {
      return (
        <div
          class="flexBox"
          style={{
            height: '100px',
            border: `1px solid ${props.tableBorderColor}`,
          }}
        >
          {props.bodyEmptyTips}
        </div>
      );
    };

    watch(
      () => props.tableHeader,
      () => {
        initData();
      },
      { immediate: true },
    );

    watch(
      () => textAreaContent.value,
      (val) => {
        const _idx = curTableData.value.findIndex(
          (item) => item[props.uniqueKey] === oneCellData.code,
        );
        if (_idx !== -1) {
          const _temp = curTableData.value[_idx];
          _temp[oneCellData.key] = val;
          curTableData.value[_idx] = _temp;
        }
        // this.$emit("TableDataChange", this.curTableData);
      },
      { deep: true },
    );

    return () => (
      <section class="nui-scroll nui-scroll-x">
        <Toast />
        <div style={{ display: 'flex' }}>
          <div class="flex-1">{renderPanelBody()}</div>
          <div style={{ width: '300px' }}>{renderOneCellItem()}</div>
        </div>
        {isBodyEmpty.value ? emptyBody() : null}
      </section>
    );
  },
});
